package generic;

import java.util.ArrayList;

/**
 * Created with IntelliJ IDEA.
 * Description：
 * User：user
 * DATE:2021-11-13
 * Time:13:55
 */

/*
泛型学习的意义：大家只要能看得懂代码即可
泛型只是在编译的时候的一种机制，叫做擦除机制，会把泛型类型当中的T擦除为Object
在运行的时候，是没有泛型的概念的
泛型的作用：自动进行类型检查，自动进行类型转换
一个泛型类是可以继承另一个泛型类的  比如之前学的comparable compareto
通配符的上界Collection<? extends E> c  通配符的上街，代表整个问号，将来可以使E类型，也可以使E的子类类型
<? super Integer>  ？是Integer的父类类型 或者是Integer自己
通配符的下届
 */
class MyStack<T>{
    public  T[] elem = (T[]) new Object[2];
    public  int usedSize;
    public  void push(T val){
        this.elem[usedSize] = val;
    }
    public  T getTop(){
        return  this.elem[usedSize - 1];
    }
}
//写一个泛型类 找到泛型数组当中的最大值
class Alg<T extends Comparable<T>>{//泛型的边界 拦着他擦到comparable就停止，泛型的上界
   //普通的泛型方法
    public T findMax(T[] array){
        T max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(max.compareTo(array[i]) < 0){//指定泛型的时候规定实现了 compareable接口，实现了compareto方法，可以进行比较
                //此处会直接报错，因为泛型不知道具体指定的是什么类型
                //T放的是引用类型，比较的时候需要使用的comparable comparetor
                max = array[i];
            }
        }
        return  max;
    }
}
class A{

}
class Alg2{
    //静态泛型类的定义
    //泛型方法：staic修饰的泛型方法
    public static<T extends  Comparable<T>> T findMax(T[] array){
        T max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(max.compareTo(array[i]) < 0){//指定泛型的时候规定实现了 compareable接口，实现了compareto方法，可以进行比较
                //此处会直接报错，因为泛型不知道具体指定的是什么类型
                //T放的是引用类型，比较的时候需要使用的comparable comparetor
                max = array[i];
            }
        }
        return  max;
    }
}
class GenericTest{
    public static<T> void print(ArrayList<T> list){//至少知道是T类型
        for (T t :list) {
            System.out.println(t);
        }
    }

    public static void print2(ArrayList<?> list){//根本不知道是什么类型
        for (Object t :list) {
            System.out.println(t);
        }
    }
}
public class test {

    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        GenericTest.print(arrayList);
        GenericTest.print2(arrayList);
    }
    public static void main5(String[] args) {
        Integer[] array = {1,2,31,4};
        System.out.println(Alg2.findMax(array));//静态泛型方法的调用，根据传给实参的数据类型，推导出形参的类型是啥
        System.out.println(Alg2.<Integer>findMax(array));//语法比较怪
     }
    public static void main4(String[] args) {
        Alg<Integer> alg = new Alg<>();
        Alg<String> alg2 = new Alg<>();
        //Alg<A> alg3 = new Alg<>();此处会报错是因为规定了必须实现comparable接口，A类型没有实现compara接口
        Integer[] array = {1,2,3,5};//不建议给int会报错的
        System.out.println(alg.findMax(array));

    }

    public static void main2(String[] args) {
        MyStack myStack = new MyStack();//此处不指定类型的话  之后都会乱套的，既可以放任意类型的数据元素
        myStack.push(1);
        myStack.push("aaaa");
    }
    public static void main1(String[] args) {
        MyStack<Integer> myStack = new MyStack<>();
        myStack.push(1);//泛型自动进行类型检查
        int val = myStack.getTop();//泛型自动进行类型转换
        MyStack<String> myStack1 = new MyStack<>();
    }
}
